﻿using System.IO;
using System.Linq;
using System.Web;
using System.Xml;
using System.Xml.Linq;
using System.Xml.XPath;
using System.Collections.Generic;

namespace EditRegion.MVC.Repository.Xml
{
    public class XmlRepository : IContentRepository
    {
        private readonly FileSystemInfo fileInfo;
        private readonly XDocument contentDoc;
        private readonly XmlDocument contentXmlDocument;

        private XElement Root
        {
            get
            {
                return contentDoc.XPathSelectElement("EditRegions");
            }
        }

        private static string contentFile;

        private static string ContentFileInAppData
        {
            get { return Path.Combine(HttpContext.Current.Server.MapPath("~/App_Data"), "EditRegions.xml"); }
        }

        public XmlRepository(): this(new FileInfo(ContentFileInAppData))
        {
            //nothing
        }

        public XmlRepository(FileSystemInfo fileInfo)
        {
            contentFile = fileInfo.FullName;
            CreateEmptyContentFileIfNeeded();
            this.fileInfo = fileInfo;
            contentXmlDocument = new XmlDocument();
            contentXmlDocument.Load(fileInfo.FullName);
            contentDoc = XDocument.Parse(contentXmlDocument.InnerXml);
        }

        private static void CreateEmptyContentFileIfNeeded()
        {
            if (File.Exists(contentFile))
            {
                return;
            }

            using (TextWriter tw = new StreamWriter(contentFile))
            {
                tw.WriteLine("<?xml version=\"1.0\" encoding=\"utf-8\"?><EditRegions/>");
                tw.Close();
            }
        }

        #region IContentRepository Members

        public bool IsExisting(string contentId)
        {
            return (from content in contentDoc.Descendants("EditRegions").Descendants()
                    where content.Attribute("id").Value.Equals(contentId)
                    select content.Value).Count() > 0;
        }

        public string GetById(string contentId)
        {
            return (from content in contentDoc.Descendants("EditRegions").Descendants()
                    where content.Attribute("id").Value.Equals(contentId)
                    select content.Value).FirstOrDefault();
        }

        public IEnumerable<KeyValuePair<string, string>> GetAll()
        {
            return (from content in contentDoc.Descendants("EditRegions").Descendants()
                    select new KeyValuePair<string, string>(content.Attribute("id").Value, content.Value)).ToList();
        }

        public void Add(string contentId, string content)
        {
            XElement element = CreateRegionElement(contentId, content);
            Root.Add(element);
            contentDoc.Save(fileInfo.FullName);
        }

        private static XElement CreateRegionElement(string contentId, string content)
        {
            XElement element = new XElement("EditRegion", new XCData(content));
            element.SetAttributeValue("id", contentId);
            return element;
        }

        public void Update(string contentId, string content)
        {
            XElement element = GetElement(contentId);
            element.ReplaceNodes(new XCData(content));
            contentDoc.Save(fileInfo.FullName);
        }

        public void Delete(string contentId)
        {
            XElement element = GetElement(contentId);
            element.Remove();
        }

        #endregion

        private XElement GetElement(string contentId)
        {
            return (from content in contentDoc.Descendants("EditRegions").Descendants()
                    where content.Attribute("id").Value.Equals(contentId)
                    select content).FirstOrDefault();
        }
    }
}
